/// \file
#ifndef debuglines_h__
#define debuglines_h__
#include "util/singleton.h"
#include "colour.h"
#include "math/vector.h"
#include "gtl/list.h"
#include "system/criticalsection.h"

namespace gecko
{

// forward declare types
class IRenderer;

// Class to provide a mechanism for drawing lines and text to the screen for debug purposes.
class DebugDraw
{
public:
	struct DebugLine
	{
		Vector3f Start;
		Vector3f End;
		Colour StartColour;
		Colour EndColour;
	};

	typedef gtl::List<DebugLine> DebugLineBuffer;

	// register this with a renderer
	void Register(IRenderer* renderer);

	// draw a line in 3D space.
	void Line3D(const Vector3f& start, const Vector3f& end, const Colour& startColour, const Colour& endColour);

	// swaps the line buffers ready for next frame
	void SwapBuffers();

	// lock the line buffer
	void Lock(DebugLineBuffer& lineBuffer);

	// unlock the line buffer
	void Unlock();

	// returns true if buffers are not empty
	bool NeedsRendering();
	
private:
	// private constructor
	DebugDraw();

	// double buffered debug line list
	DebugLineBuffer m_DebugLineBuffer[2];
	unsigned int m_CurrentBuffer;
	IRenderer* m_Renderer;
	CriticalSection m_CritialSection;

	// allow the manager to instantiate this class
	friend class DebugDrawManager;
};

// Class to manager debug drawing.  The manager is multi-threaded and provides a separate drawer per-thread.
class DebugDrawManager : public Singleton<DebugDrawManager>
{
public:
	// Register this with a renderer
	void Register(IRenderer* renderer);

	// Draw a line in 3D space.
	void Line3D(const Vector3f& start, const Vector3f& end, const Colour& startColour, const Colour& endColour);
	
	// Swaps the line buffers ready for next frame (should be called on each thread)
	void SwapBuffers();

	// get one of the debug drawers
	DebugDraw* GetDrawer(unsigned int id);
	
	// return the drawer count
	unsigned int GetNumDrawers();

private:
	static const int MAX_DEBUGDRAWERS = 64;
	DebugDraw m_DebugDrawers[MAX_DEBUGDRAWERS];
};

} // namespace gecko

#endif
